package com.xbongbong.paas.help;

import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.enums.SerialDateEnum;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.field.SerialNumberPoJo;
import com.xbongbong.paas.pojo.dto.SerialNoDTO;
import com.xbongbong.paas.pojo.vo.SerialNoVO;
import com.xbongbong.paas.redis.PaasRedisHelper;
import com.xbongbong.paas.redis.RedisPrefixConstant;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.DateUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.pro.enums.errorcodes.BuinessDefaultErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.saas.constant.BasicConstant;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

@Component
public class SerialNoHelp {

    private static final Logger LOG = LoggerFactory.getLogger(SerialNoHelp.class);

    @Resource
    private PaasRedisHelper paasRedisHelper;

    public List<String> getSerialNoListByFormId(String corpid, Long formId, Map<String, FieldAttrEntity> explainMap, Integer count) throws XbbException {
        List<String> serialNoList = new ArrayList<>();
        if (!explainMap.containsKey(FieldTypeEnum.SERIALNO.getAlias()) || count == 0) {
            return serialNoList;
        }
        FieldAttrEntity fieldAttrEntity = explainMap.get(FieldTypeEnum.SERIALNO.getAlias());
        if (Objects.equals(1, fieldAttrEntity.getStrictController())) {
            // 严控模式开启，不需要先获取流水号
            return serialNoList;
        }
        SerialNumberPoJo serialNumber = fieldAttrEntity.getSerialNumber();
        for (int i = 0; i < count; i++) {
            // 时间类型 可选项有无，年，年月，年月日，构成编号中的日期部分
            String time = "";
            int cacheSeconds = 0;
            // 时间类型
            time = getPrefixTime(serialNumber, time);
            // 缓存时间
            cacheSeconds = getSerialNoCache(serialNumber);
            // 前缀
            String prefix = serialNumber.getPrefix();
            // 后缀
            String postfix = serialNumber.getPostfix();
            // 自增位数
            Integer numberDigit = serialNumber.getNumberDigit();
            if(numberDigit < PaasConstant.DEFUALT_NUMBER_DIGIT){
                numberDigit = PaasConstant.DEFUALT_NUMBER_DIGIT;
            }
            // 自增起始值
            Integer startNum = serialNumber.getStartNum();
            if(startNum == null || startNum < 0) {
                startNum = 1;
            }
            String timeS ="";
            timeS = getSeriTime(serialNumber, timeS);
            String filePrefix = RedisPrefixConstant.SERIAL_NO_PREFIX + prefix + timeS;
            if (Objects.isNull(formId)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100002, SystemErrorCodeEnum.API_ERROR_100002.getMsg());
            }
            String key = corpid + formId.toString();
            Long incrNumber = paasRedisHelper.getIncrNumByOne(filePrefix, key, cacheSeconds, startNum);

            String decimalFormatStr = "%0" + numberDigit + "d";
            String incrNumberFormat = String.format(decimalFormatStr, incrNumber);
            String serialNo = prefix + time + incrNumberFormat + postfix;
            serialNoList.add(serialNo);
        }
        return serialNoList;
    }

    /**
     * 获取流水号
     * @param serialNoDTO 流水号对象
     * @return 流水号
     */
    public SerialNoVO getSerialNo(SerialNoDTO serialNoDTO) throws XbbException {
        SerialNoVO serialNoVO = new SerialNoVO();
        try {
            SerialNumberPoJo serialNumber = serialNoDTO.getSerialNumber();
            if (Objects.isNull(serialNumber)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
            }
            String corpid = serialNoDTO.getCorpid();
            // 时间类型 可选项有无，年，年月，年月日，构成编号中的日期部分
            String time = "";
            int cacheSeconds = 0;
            // 时间类型
            time = getPrefixTime(serialNumber, time);
            String timeS ="";
            timeS = getSeriTime(serialNumber, timeS);
            // 缓存时间
            cacheSeconds = getSerialNoCache(serialNumber);
            // 前缀
            String prefix = serialNumber.getPrefix();
            // 后缀
            String postfix = serialNumber.getPostfix();
            // 自增位数
            Integer numberDigit = serialNumber.getNumberDigit();
            if(numberDigit < PaasConstant.DEFUALT_NUMBER_DIGIT){
                numberDigit = PaasConstant.DEFUALT_NUMBER_DIGIT;
            }
            // 自增起始值
            Integer startNum = serialNumber.getStartNum();
            if(startNum == null || startNum < 0) {
                startNum = 1;
            }
            String filePrefix = RedisPrefixConstant.SERIAL_NO_PREFIX + prefix + timeS;
            Long formId = serialNoDTO.getFormId();
            if (Objects.isNull(formId)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100002, SystemErrorCodeEnum.API_ERROR_100002.getMsg());
            }
            String key = corpid + formId.toString();
            Long incrNumber = paasRedisHelper.getIncrNumByOne(filePrefix, key, cacheSeconds, startNum);

            String decimalFormatStr = "%0" + numberDigit + "d";
            String incrNumberFormat = String.format(decimalFormatStr, incrNumber);
            String serialNo = prefix + time + incrNumberFormat + postfix;
            serialNoVO.setSerialNo(serialNo);
        } catch (XbbException e ) {
            throw e;
        } catch (Exception e ) {
            LOG.error("SerialNoUtil获取流水号失败", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return serialNoVO;
    }

    /**
     * 获取流水号前缀
     * @param serialNumber
     * @param time
     * @return
     */
    public String getPrefixTime(SerialNumberPoJo serialNumber, String time) {
        String dateFormat = serialNumber.getDateFormat();
        String date ="";
        if (StringUtil.isNotEmpty(dateFormat)){
            if (SerialDateEnum.NONE.getValue().equals(dateFormat)){
                date = "";
            }else{
                date = DateUtil.getString(new Date(), DateUtil.SDF);
            }
        }
        if (SerialDateEnum.YEAR_MONTH.getValue().equals(dateFormat)){
            time = DateUtil.getString(DateUtil.getDate(date, new SimpleDateFormat(
                    "yyyy-MM-dd HH:mm")), DateUtil.SDFMonth_NoFormat);
        }else if (SerialDateEnum.ALL.getValue().equals(dateFormat)){
            time = DateUtil.getString(DateUtil.getDate(date, new SimpleDateFormat(
                    "yyyy-MM-dd HH:mm")), DateUtil.SDFDate_NoFormat);
        }else if (SerialDateEnum.YEAR.getValue().equals(dateFormat)){
            time = DateUtil.getString(DateUtil.getDate(date, new SimpleDateFormat(
                    "yyyy-MM-dd HH:mm")), DateUtil.SDFYears);
        }
        return time;
    }

    public String getSeriTime(SerialNumberPoJo serialNumber, String time) {
        String dateFormat = serialNumber.getDateFormat();
        Integer resetCycle = serialNumber.getResetCycle();
        String date ="";
        if (StringUtil.isNotEmpty(dateFormat)){
            if (SerialDateEnum.NONE.getValue().equals(dateFormat)){
                date = "";
            }else{
                date = DateUtil.getString(new Date(), DateUtil.SDF);
            }
        }
        if (Objects.equals(serialNumber.getResetCycle(), BasicConstant.ZERO) || StringUtil.isEmpty(date)){
            time = "";
        } else if (Objects.equals(serialNumber.getResetCycle(), BasicConstant.ONE)) {
            time = DateUtil.getString(DateUtil.getDate(date, new SimpleDateFormat(
                    "yyyy-MM-dd HH:mm")), DateUtil.SDFDate_NoFormat);
        } else if (Objects.equals(serialNumber.getResetCycle(), BasicConstant.TWO)){
            time = DateUtil.getString(DateUtil.getDate(date, new SimpleDateFormat(
                    "yyyy-MM-dd HH:mm")), DateUtil.SDFMonth_NoFormat);
        }else  if (Objects.equals(serialNumber.getResetCycle(), BasicConstant.THREE)){
            time = DateUtil.getString(DateUtil.getDate(date, new SimpleDateFormat(
                    "yyyy-MM-dd HH:mm")), DateUtil.SDFYears);
        } else{
            if (SerialDateEnum.YEAR_MONTH.getValue().equals(dateFormat)){
                time = DateUtil.getString(DateUtil.getDate(date, new SimpleDateFormat(
                        "yyyy-MM-dd HH:mm")), DateUtil.SDFMonth_NoFormat);
            }else if (SerialDateEnum.ALL.getValue().equals(dateFormat)){
                time = DateUtil.getString(DateUtil.getDate(date, new SimpleDateFormat(
                        "yyyy-MM-dd HH:mm")), DateUtil.SDFDate_NoFormat);
            }else if (SerialDateEnum.YEAR.getValue().equals(dateFormat)){
                time = DateUtil.getString(DateUtil.getDate(date, new SimpleDateFormat(
                        "yyyy-MM-dd HH:mm")), DateUtil.SDFYears);
            }
        }
        return time;
    }

    /**
     * 获取缓存的时间
     * @param serialNumber
     * @return
     */
    public int getSerialNoCache(SerialNumberPoJo serialNumber) {
        Integer resetCycle = serialNumber.getResetCycle();
        int cacheSeconds;
        Integer days = 0;
        if (Objects.equals(resetCycle, BasicConstant.ONE)){
            days =1;
        }else if (Objects.equals(resetCycle, BasicConstant.TWO)){
            days = DateUtil.getCurrentMonthDays();
        } else if (Objects.equals(resetCycle, BasicConstant.THREE)) {
            days = DateUtil.getCurrentYearDays();;
        }
        cacheSeconds =  (int)(TimeUnit.DAYS.toSeconds(days));
        return cacheSeconds;
    }

    /**
     * 生成流水号
     * @param serialNo 回款单编号
     * @param corpid 公司id
     * @param formId 表单id
     * @param fieldAttrEntity 字段实体
     * @return java.lang.String
     * @throws XbbException
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    public String getSerialNo(String serialNo, String corpid, Long formId, FieldAttrEntity fieldAttrEntity) throws XbbException {
        if (Objects.nonNull(fieldAttrEntity) && fieldAttrEntity.getFieldType() != null && fieldAttrEntity.getFieldType().equals(FieldTypeEnum.SERIALNO.getType())) {
            SerialNoDTO serialNoDTO = new SerialNoDTO();
            serialNoDTO.setCorpid(corpid);
            serialNoDTO.setFormId(formId);
            serialNoDTO.setSerialNumber(fieldAttrEntity.getSerialNumber());
            // 生成流水号
            SerialNoVO serialNoVO = getSerialNo(serialNoDTO);
            if (serialNoVO == null || StringUtil.isEmpty(serialNoVO.getSerialNo())) {
                throw new XbbException(BuinessDefaultErrorCodeEnum.API_ERROR_200026);
            }
            serialNo = serialNoVO.getSerialNo();
        }
        return serialNo;
    }
}
